<template>
	<view class="col full-width">
		<button v-if="addButton" class="upload-file-button" :style="uploadButtonStyle" @click="handleChooseFile" type="primary" size="mini">{{uploadButtonText}}</button>
		<view class="col">
			<file-link 
				v-for="(file, fileIndex) in uploadCacheList" 
				:key="fileIndex" 
				v-model="uploadCacheList[fileIndex]">
				<template v-slot:footer>
					<view v-if="deleteButton" class="upload-file-footer" @click.stop="handleRemoveImage(fileIndex)">
						<uni-icons type="closeempty" color="#FFFFFF" size="15"></uni-icons>
					</view>
				</template>
			</file-link>
		</view>
	</view>
</template>

<script>
import { getFileName, getExtensionName } from "@/utils/file";
import { getToken } from "@/utils/auth";
import { deleteFile } from "@/api/common/upload.js"
import config from '@/config'
import FileLink from "@/components/file-link/index.vue"

export default {
	model: {
		prop: 'value',
		event: 'input'
	},
	components: { FileLink },
	data() {
		return {
			uploadLen: 0,
			uploadCacheList: [],
			uploadBeforeList: [],
			fileUrls: []
		};
	},
	name: 'UploadFile',
	props: {
		/** 绑定的文件列表 */
		value: {
			type: String, 
			default: ''
		},
		/** 上传数量 */
		limit: {
			type: [Number, String],
			default: 9
		},
		/** 上传按钮样式 */
		uploadButtonStyle: {
			type: String,
			default: ''
		},
		/** 是否显示添加按钮 */
		addButton: {
			type: Boolean,
			default: true
		},
		/** 是否显示删除按钮 */
		deleteButton: {
			type: Boolean,
			default: true
		},
	},
	watch: {
		value: function(n, o) {
			let files = n?n.split(","):[];
			this.uploadBeforeList = files.filter(path=>path).map(path=>{
				const fileName = getFileName(path);
				const fileExtension = getExtensionName(path);
				return {
					fileName: path,
					newFileName: fileName,
					fileExtension: fileExtension,
					path: config.baseUrl + path,
					upload_percent: 100
				}
			});
			this.uploadCacheList = this.uploadBeforeList;
			this.uploadLen = this.uploadBeforeList.length;
		}
	},
	computed: {
		/** 更新按钮显示的内容 */
		uploadButtonText() {
			return this.$i18n?this.$i18n.t('upload.select-file'):'Select File';
		},
		/** 获取文件Url路径 */
		fileUrl: function() {
			return function(file) {
				return config.baseUrl + file.fileName;
			}
		},
	},
	async created() {
	},
	methods: {
		/** 上传文件 */
		uploadFile(files,header) {
			let self = this;
			// 遍历所有文件路径进行上传
			const promises = files.map(function(file) {
				const params = {
					url: config.baseUrl + "/common/upload",
					path: file.path,
					name: 'file',
					data: {
						customFileName: file.name
					},
					header: {
						Authorization: "Bearer " + getToken(),
					},
					self: self
				}
				return promisify(upload)(params);
			});
			uni.showLoading({
				title: this.$i18n.t('upload.uploading')
			});
			// 当所有文件都上传完成后执行以下代码
			Promise.all(promises)
				.then(function(data) {
					uni.hideLoading();
					self.uploadCacheList.push(...data);
					self.emit();
				})
				.catch(function(res) {
					console.error(res)
					uni.hideLoading();
				});
		},
		/** 选择文件 */
		handleChooseFile() {
			let self = this;
			// #ifdef H5
			uni.chooseFile({
				count: self.limit - self.uploadBeforeList.length,
				type: 'all',
				success: function(res) {
					self.handleChooseFileSuccess(res);
				},
				fail: function(err) {
					self.handleChooseFileFail(err);
				}
			});
			// #endif
			// #ifdef MP-WEIXIN
			wx.chooseMessageFile({
				count: self.limit - self.uploadBeforeList.length,
				type: 'all',
				success: function(res) {
					self.handleChooseFileSuccess(res);
				},
				fail: function(err) {
					self.handleChooseFileFail(err);
				}
			});
			// #endif
		},
		/** 处理选择文件成功事件 */
		handleChooseFileSuccess(res) {
			for (let i = 0, len = res.tempFiles.length; i < len; i++) {
				res.tempFiles[i]['upload_percent'] = 0;
				this.uploadBeforeList.push(res.tempFiles[i]);
			}
			const uploadCache = res.tempFiles.map(f=>{
				return {
					name: f.name,
					path: f.path,
				}
			});
			this.uploadFile(uploadCache);
		},
		/** 处理选择文件失败事件 */
		handleChooseFileFail(err) {
			uni.showToast({
				title: err
			})
		},
		/** 处理删除文件 */
		handleRemoveImage(idx) {
			let self = this;
			uni.showModal({
				title: this.$i18n.t('prompted'),
				content: this.$i18n.t('upload.file-delete-prompt'),
				showCancel: true,
				cancelText: this.$i18n.t('cancel'),
				confirmText: this.$i18n.t('delete'),
				success: (res) => {
					if(res.confirm) {
						// 获取要删除的文件信息
						const removeFile = self.uploadCacheList[idx];
						uni.showLoading({
							title: this.$i18n.t('upload.file-deleting')
						})
						// 调用删除文件接口
						deleteFile({
							fileName: removeFile.fileName
						}).then(res=>{
							uni.hideLoading();
							self.uploadBeforeList.splice(idx, 1);
							self.uploadCacheList.splice(idx, 1);
							self.uploadLen = self.uploadBeforeList.length;
							uni.showToast({
								title: this.$i18n.t('upload.file-delete-success')
							});
							self.emit();
						}).catch(err=>{
							uni.hideLoading();
						});
					}
				}
			});
		},
		emit() {
			this.$emit('input', this.uploadCacheList.map(f=>f.fileName).join(','));
		},
		handleViewFile(file) {
			if(isView(file)) {
				uni.downloadFile({
					url: this.fileUrl(file),
				});
			} else {
				uni.showLoading({
					title: `此文件无法预览`
				});
			}
		},
	}
};

const promisify = api => {
	return function(options, ...params) {
		return new Promise(function(resolve, reject) {
			api(
				Object.assign({}, options, {
					success: resolve,
					fail: reject
				}),
				...params
			);
		});
	};
};

const upload = function(options) {
	let { url, self, path, name, data, header, success, progress, fail } = options;
	const uploadTask = uni.uploadFile({
		url: url,
		filePath: path,
		name: name,
		formData: data,
		header: header,
		success: function(res) {
			var data = res.data;
			try {
				data = JSON.parse(res.data);
			} catch (e) {
				throw (e, data);
			}
			if (res.statusCode === 200) {
				if (success) {
					success(data);
				}
			} else {
				if (fail) {
					fail(data);
				}
			}
		},
		fail: function(res) {
			if (fail) {
				fail(res);
			}
		}
	});
	uploadTask.onProgressUpdate(async function(res) {
		for (let i = 0, len = self.uploadBeforeList.length; i < len; i++) {
			self.uploadBeforeList[i]['upload_percent'] = await res.progress;
		}
		self.uploadBeforeList = self.uploadBeforeList;
		self.uploadLen = self.uploadBeforeList.length;
	});
};
</script>

<style lang="scss" scoped>
.upload-file-button {
	margin-left: 0;
	margin-top: 14rpx;
	margin-bottom: 20rpx;
}
.upload-file-footer {
	display: inline-flex;
	justify-content: center;
	align-items: center;
	width: 60rpx;
	height: 60rpx;
	border-radius: 10rpx;
	background-color: #e43d33;
	flex-shrink: 0;
}
</style>
